using System;
using System.Globalization;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Xml;
using System.Reflection;
using JigLibX.Physics;
using JigLibX.Collision;
using Services;
using Utilities.Menu.UIElements;
using BowMaster.Resources;
using Services.Menu;
using Utilities;

namespace BowMaster.Menu
{
    class LevelSelectMenu : DrawableGameComponent
    {

        GraphicsDeviceManager GraphicsDeviceManager;
        InputManager input_manager;
        Texture2D buttonbg, level_bg, bg_text, upper_bg_box;
        SpriteFont arial18, arial14;
        MyButton cancel;
        SpriteBatch spriteBatch;
        StateManager StateManager;
        ArrayList<MyButton> levels;
        ArrayList<MyButton> levels_num;
        //Vector2 titlePos;
        protected float press_wait;
        protected readonly float PRESS_INTERVAL = 0.5f;
        //Rectangle frame_rect;
        public LevelSelectMenu(Game game, GraphicsDeviceManager graphics)
            : base(game)
        {
            this.GraphicsDeviceManager = graphics;
        }

        public override void Initialize()
        {
            spriteBatch = Game.Services.GetService(typeof(SpriteBatch)) as SpriteBatch;
            StateManager = Game.Services.GetService(typeof(AStateManager)) as StateManager;
            input_manager = new InputManager(Game);
            Game.Components.Add(input_manager);
            input_manager.OnTap += on_tap;
            //input_manager.OnDoubleTap += on_double_tap;
            //input_manager.OnPress += on_double_tap;
            input_manager.OnDrag += on_drag;
            input_manager.OnVerticalDrag += on_drag;
            input_manager.OnHorizontalDrag += on_drag;
            input_manager.OnDragCompleted += on_drag_completed;

#if !WINDOWS && !XBOX
            input_manager.OnDrag += on_drag;
            input_manager.OnVerticalDrag += on_drag;
            input_manager.OnDragCompleted += on_drag_completed;
#endif
            base.Initialize();
        }
        int initial_x = 20;
        int initial_y = 60;
        int level_button_w = 370;
        int level_button_h = 50;
        int level_offset = 20;
        int levels_to_show = 8;
        int current_first = 0;
        int buttons_h = 70;
        
        int final_y; //NON RIMUOVERE, serve per la versione windows
        Rectangle upperBlack, lowerBlack;//NON RIMUOVERE, serve per la versione emulata
        Texture2D whiteTexture;//NON RIMUOVERE, serve per la versione emulata
        int lower_y, upper_y;//NON RIMUOVERE, serve per la versione emulata
        MyButton status_b;//NON RIMUOVERE, serve per la versione emulata

        MyButton title1, title2;
        //MyButton worldRecord;//NON RIMUOVERE, serve per la versione emulata
        //bool recordPresent;
        protected override void LoadContent()
        {
            whiteTexture = Game.Content.Load<Texture2D>("Textures/whitePixel");
            initial_x = 80;

            level_button_w = 380;

            buttons_h = 70;
            initial_y = 220;
            level_button_h = 50;
            level_offset = 20;
            final_y = levels_to_show * (buttons_h + level_offset) - level_offset + initial_y;
            //bar_height = levels_to_show * (buttons_h + level_offset) - level_offset;
            buttonbg = Game.Content.Load<Texture2D>("Textures/whitePixel");
            level_bg = Game.Content.Load<Texture2D>("Textures/whitePixel");

            //bar = Game.Content.Load<Texture2D>("Levels/bar");
            //frame = Game.Content.Load<Texture2D>("Levels/frame");
            arial18 = Game.Content.Load<SpriteFont>("Fonts/Arial18Ptx");
            arial14 = Game.Content.Load<SpriteFont>("Fonts/Arial14Ptx");
            var emptyTexture = Game.Content.Load<Texture2D>("Textures/emptyPixel");
            //cancel = new MyButton(new Rectangle(0, 700, 480, 100), Strings.Menu_Back, Color.Blue, arial18, Color.White, Game.Content.Load<Texture2D>("Levels/back"));
            cancel = new MyButton(new Rectangle(200, 745, 80, 55), Strings.Menu_Back, Color.White, arial18, TextPos.Center, Game.Content.Load<Texture2D>("Textures/bar_box"), Color.White);
            //title = new MyButton(new Rectangle(initial_x, 50, level_button_w, 70), Strings.Menu_SelectLevel, Color.Blue, arial18, Color.CornflowerBlue, buttonbg);
            levels = new ArrayList<MyButton>();
            levels_num = new ArrayList<MyButton>();
            //titlePos = new Vector2(240, 50) - arial18.MeasureString(title) / 2;

            for (int i = 0; i < StateManager.levels.Count; i++)
            {
                float f = ((float)i) / StateManager.levels.Count;
                var l = StateManager.levels[i];
                var name = l.Name;
                if (StateManager.GameState.Available[i] && StateManager.GameState.Records[i] < 10000)
                    name += "\n" + Strings.Menu_Record + ": " + StateManager.GameState.Records[i];
                var rect = new Rectangle(initial_x, initial_y + (level_button_h + level_offset) * i, level_button_w, level_button_h);
                levels.Add(new MyButton(rect,
                    name,
                    StateManager.GameState.Available[i] ? textColor : Color.Gray,
                    //textColor,
                    arial18,
                    TextPos.Center
                    ));

                levels_num.Add(new MyButton(new Rectangle(initial_x, initial_y + (level_button_h + level_offset) * i, 50, level_button_h),
                    "" + (i + 1) + ")",
                    Color.White,
                    arial18,
                    TextPos.Center,
                    whiteTexture,
                    StateManager.GameState.Available[i] ? textColor : Color.Gray
                    ));
            }
            //prevLevels = new MyButton(new Rectangle(initial_x, initial_y - 20 - level_button_h / 2, level_button_w, level_button_h / 2), "", Color.White, null, Color.White, prevLevels_t);
            //nextLevels = new MyButton(new Rectangle(initial_x, initial_y + 20 + (level_button_h + level_offset) * levels_to_show-level_offset, level_button_w, level_button_h / 2), "", Color.White, null, Color.White, next_levels_t);
            //frame_rect = new Rectangle(initial_x - 20, initial_y - 20, 40 + level_button_w, 40 + (level_button_h + level_offset) * levels_to_show - level_offset);
            //velocity = 0;

            //bar_rect = new Rectangle(bar_x, initial_y, bar_width, bar_height);
            //indicator_rect = new Rectangle(bar_x, initial_y, bar_width, 10);
            
            upperBlack = new Rectangle(0, 0, 480, initial_y);
            lowerBlack = new Rectangle(0, 800 - 160, 480, 160);
            upper_y = initial_y + levels.Count * (level_button_h + level_offset);
            lower_y = lowerBlack.Y - levels.Count * (level_button_h + level_offset);

            int completed = 0;

            for (int i = 0; i < levels.Count; i++)
                if (StateManager.GameState.Available[i] && StateManager.GameState.Records[i] <= 1000)
                    completed++;
                

            status_b = new MyButton(new Rectangle(0, lowerBlack.Y + 10, 480, 40), Strings.Menu_Completed + completed + " / " + levels.Count, Color.White, arial18, TextPos.Center , whiteTexture, Color.Black);

            //worldRecord = new MyButton(new Rectangle(initial_x, status_b.rectangle.Y + 70, level_button_w, 30), Strings.Menu_WorldRecord + record, Color.White, arial18, Color.Black, whiteTexture);

            //recordPresent = record != 0;
            //recordPresent = true;

            title1 = new MyButton(new Rectangle(0, 0, 480, 100), Strings.Menu_Title, textColor, Game.Content.Load<SpriteFont>("Fonts/Arial54Ptx"));
            title2 = new MyButton(new Rectangle(0, 100, 480, 100), Strings.Menu_SelectLevel, textColor, Game.Content.Load<SpriteFont>("Fonts/Arial42Ptx"));

            bg_text = Game.Content.Load<Texture2D>("Textures/bg_port");
            upper_bg_box = Game.Content.Load<Texture2D>("Textures/upper_bg_box");
            base.LoadContent();
        }
        protected override void Dispose(bool disposing)
        {
            Game.Services.RemoveService(typeof(IInputManager));
            base.Dispose(disposing);
        }


        public override void Update(GameTime gameTime)
        {
            var dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (press_wait < PRESS_INTERVAL)
                press_wait += dt;
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                StateManager.SelectMainMenu();
                return;
            }

            if (velocity != 0)
            {
                if (velocity < 0)
                {
                    velocity += dt;
                    if (velocity > 0)
                        velocity = 0;
                }
                else
                {
                    velocity -= dt;
                    if (velocity < 0)
                        velocity = 0;
                }

            }
            if (velocity != 0)
            {
                var delta_y = (int)velocity * 2;
                if (levels[levels.Count - 1].rectangle.Y + delta_y < lowerBlack.Y - buttons_h)//- level_button_h)
                {
                    delta_y = levels[levels.Count - 1].rectangle.Y - lowerBlack.Y + buttons_h;// + level_button_h;
                    velocity = 0;
                }
                else
                    if (levels[levels.Count - 1].rectangle.Y + delta_y + buttons_h > upper_y)
                    {
                        delta_y = levels[levels.Count - 1].rectangle.Y + buttons_h - upper_y;
                        velocity = 0;
                    }

                for (int i = 0; i < levels.Count; i++)
                {

                    levels[i].position.Y += delta_y;
                    levels[i].rectangle.Y += delta_y;
                    levels_num[i].rectangle.Y = levels[i].rectangle.Y;
                }

            }

            base.Update(gameTime);
        }
        Color textColor = new Color(8, 141, 217);
        Rectangle bg_rect = new Rectangle(0, 0, 480, 800);
        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();


            spriteBatch.Draw(bg_text, bg_rect, Color.White);
            for (int i = 0; i < levels.Count; i++)
            {

                levels[i].Draw(spriteBatch);
                levels_num[i].Draw(spriteBatch);

            }
            spriteBatch.Draw(upper_bg_box, upperBlack, Color.White);
            spriteBatch.Draw(whiteTexture, lowerBlack, Color.Black);

            title1.Draw(spriteBatch);
            title2.Draw(spriteBatch);

            status_b.Draw(spriteBatch);

            cancel.Draw(spriteBatch);

            spriteBatch.End();
            base.Draw(gameTime);
        }
        Point tp = new Point();
        void on_tap(Vector2 tap_position)
        {

            if (press_wait < PRESS_INTERVAL) return;
            if (velocity != 0)
                velocity = 0;
            else
            {
                tp.X = (int)tap_position.X;
                tp.Y = (int)tap_position.Y;
                if (cancel.tapped_on(tp))
                    StateManager.SelectMainMenu();
                else for (int i = 0; i < levels.Count; i++)
                        if (levels[i].tapped_on(tp) && /*StateManager.GameState.Available[i] &&*/ !upperBlack.Contains(tp) && !lowerBlack.Contains(tp))
                            StateManager.SelectLevel(i);
            }
        }
        
        Vector2 old_drag_position = Vector2.Zero;
        float velocity;
        void on_drag(Vector2 drag_pos)
        {
            if (old_drag_position != Vector2.Zero)
            {

                var distance = Vector2.Distance(old_drag_position, drag_pos) / 100;
                //if (distance >= 20)
                //{
                if (drag_pos.Y > old_drag_position.Y)
                {
                    if (velocity < 0)
                        velocity = 0;
                    velocity += distance;
                    velocity = Math.Min(velocity, 20);
                }
                else if(drag_pos.Y < old_drag_position.Y)
                {
                    if (velocity > 0)
                        velocity = 0;
                    velocity -= distance;
                    velocity = Math.Max(velocity, -20);
                }
            }
            //else
            //    velocity = 0;
            old_drag_position = drag_pos;
        }
        void on_drag_completed()
        {
            old_drag_position = Vector2.Zero;
        }
        private Vector2 centerString(String text, SpriteFont font, Rectangle rectangle)
        {
            Vector2 textPosition = new Vector2();
            if (text == null || text == "")
            {
                textPosition.X = rectangle.Center.X;
                textPosition.Y = rectangle.Center.Y;
                return textPosition;
            }
            var dimStringa = font.MeasureString(text);

            textPosition.X = rectangle.X + rectangle.Width / 2 - dimStringa.X / 2;
            textPosition.Y = rectangle.Y + rectangle.Height / 2 - dimStringa.Y / 2;

            textPosition += font.MeasureString(text) / 2.0f;
            return textPosition;
        }
    }
}
